package com.eva.service.system.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.eva.dao.system.SystemPermissionMapper;
import com.eva.dao.system.dto.DeleteSystemPermissionDTO;
import com.eva.dao.system.model.SystemPermission;
import com.eva.dao.system.vo.SystemPermissionListVO;
import com.eva.service.system.SystemPermissionService;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 系统权限Service实现
 *
 * @author Eva.Caesar Liu
 * @since 2022/05/09 19:56
 */
@Service
public class SystemPermissionServiceImpl implements SystemPermissionService {

    @Autowired
    private SystemPermissionMapper systemPermissionMapper;

    @Override
    public Integer create(SystemPermission systemPermission) {
        systemPermissionMapper.insert(systemPermission);
        return systemPermission.getId();
    }

    @Override
    public void deleteById(Integer id) {
        SystemPermission systemPermission = new SystemPermission();
        systemPermission.setId(id);
        systemPermission.setDeleted(Boolean.TRUE);
        this.updateById(systemPermission);
    }

    @Override
    @Transactional
    public void deleteByIdInBatch(List<Integer> ids) {
        if (CollectionUtils.isEmpty(ids)) return;
        for (Integer id : ids) {
            this.deleteById(id);
        }
    }

    @Override
    public void delete(DeleteSystemPermissionDTO dto) {
        UpdateWrapper<SystemPermission> deleteWrapper = new UpdateWrapper<>();
        deleteWrapper.lambda()
                .set(SystemPermission::getDeleted, Boolean.TRUE)
                .eq(dto.getId() != null, SystemPermission::getId, dto.getId())
                .likeLeft(dto.getModulePrefix() != null, SystemPermission::getModule, dto.getModulePrefix());
        systemPermissionMapper.update(null, deleteWrapper);
    }

    @Override
    public void deleteInBatch(List<DeleteSystemPermissionDTO> dtos) {
        if (CollectionUtils.isEmpty(dtos)) {
            return;
        }
        for (DeleteSystemPermissionDTO dto : dtos) {
            this.delete(dto);
        }
    }

    @Override
    public void updateById(SystemPermission systemPermission) {
        systemPermissionMapper.updateById(systemPermission);
    }

    @Override
    @Transactional
    public void updateByIdInBatch(List<SystemPermission> systemPermissions) {
        if (CollectionUtils.isEmpty(systemPermissions)) return;
        for (SystemPermission systemPermission : systemPermissions) {
            this.updateById(systemPermission);
        }
    }

    @Override
    public SystemPermission findById(Integer id) {
        return systemPermissionMapper.selectById(id);
    }

    @Override
    public List<SystemPermission> findByUserId(Integer userId) {
        return systemPermissionMapper.selectByUserId(userId);
    }

    @Override
    public List<SystemPermission> findByRoleId(Integer roleId) {
        return systemPermissionMapper.selectByRoleId(roleId);
    }

    @Override
    public SystemPermission findOne(SystemPermission systemPermission) {
        Wrapper<SystemPermission> wrapper = new QueryWrapper<>(systemPermission);
        return systemPermissionMapper.selectOne(wrapper);
    }

    @Override
    public List<SystemPermission> findList(SystemPermission systemPermission) {
        Wrapper<SystemPermission> wrapper = new QueryWrapper<>(systemPermission);
        return systemPermissionMapper.selectList(wrapper);
    }

    @Override
    public List<SystemPermissionListVO> findTree() {
        List<SystemPermissionListVO> permissionList = systemPermissionMapper.selectManageList();
        List<SystemPermissionListVO> tree = new ArrayList<>();
        for (SystemPermissionListVO permission : permissionList) {
            // 没有模块的权限默认归属为"其它"模块
            if (StringUtils.isBlank(permission.getModule())) {
                permission.setModule("其它");
            }
            // 分解模块
            String[] modulePaths = permission.getModule().split("/");
            SystemPermissionListVO target = null;
            SystemPermissionListVO parent = null;
            List<String> paths = new ArrayList<>();
            for (String path : modulePaths) {
                paths.add(path);
                // 查找模块
                target = this.getTargetNode(tree, paths);
                // 如果模块不存在，则添加一个子模块
                if (target == null) {
                    target = new SystemPermissionListVO();
                    target.setId(Integer.valueOf(RandomStringUtils.randomNumeric(6)) * -1);
                    target.setLevel(paths.size() - 1);
                    target.setType("module");
                    target.setName(path);
                    target.setModulePath(StringUtils.join(paths, "/"));
                    target.setChildren(new ArrayList<>());
                    if (parent != null) {
                        parent.getChildren().add(target);
                    } else {
                        tree.add(target);
                    }
                }
                parent = target;
            }
            // 将权限添加进模块中
            if (target != null) {
                target.getChildren().add(permission);
            }
        }
        return tree;
    }

    @Override
    public long count(SystemPermission systemPermission) {
        Wrapper<SystemPermission> wrapper = new QueryWrapper<>(systemPermission);
        return systemPermissionMapper.selectCount(wrapper);
    }

    /**
     * 查找目标节点
     * @param tree 节点树
     * @param paths 模块路径
     * @return
     */
    private SystemPermissionListVO getTargetNode(List<SystemPermissionListVO> tree, List<String> paths) {
        List<SystemPermissionListVO> list = tree;
        List<SystemPermissionListVO> nodeStack = new ArrayList<>();
        for (String path : paths) {
            if (list == null) {
                break;
            }
            for (SystemPermissionListVO permission : list) {
                if (path.equals(permission.getName()) && "module".equals(permission.getType())) {
                    nodeStack.add(permission);
                    list = permission.getChildren();
                    break;
                }
            }
        }
        return nodeStack.size() == paths.size() ? nodeStack.get(nodeStack.size() - 1) : null;
    }
}
